package net.maku.events.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fhs.trans.service.impl.TransService;
import com.github.xiaoymin.knife4j.core.util.CollectionUtils;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.maku.events.entity.ActivityQuestionBankOptionEntity;
import net.maku.events.enums.JudgmentAnserEnum;
import net.maku.events.enums.QuestionType;
import net.maku.events.service.ActivityQuestionBankOptionService;
import net.maku.events.utils.ExcelImportUtil;
import net.maku.events.vo.*;
import net.maku.framework.common.constant.Constant;
import net.maku.framework.common.utils.DateUtils;
import net.maku.framework.common.utils.ExcelUtils;
import net.maku.framework.common.utils.PageResult;
import net.maku.framework.mybatis.service.impl.BaseServiceImpl;
import net.maku.events.entity.ActivityQuestionBankEntity;
import net.maku.events.query.ActivityQuestionBankQuery;
import net.maku.events.dao.ActivityQuestionBankDao;
import net.maku.events.service.ActivityQuestionBankService;
import net.maku.framework.security.user.SecurityUser;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Sheet;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 题库题目
 *
 * @author 阿沐 babamu@126.com
 * @since 1.0.0 2025-03-22
 */
@Slf4j
@Service
@AllArgsConstructor
public class ActivityQuestionBankServiceImpl extends BaseServiceImpl<ActivityQuestionBankDao, ActivityQuestionBankEntity> implements ActivityQuestionBankService {

    private final ActivityQuestionBankOptionService activityQuestionBankOptionService;

    private final TransService transService;

    @Override
    public PageResult<ActivityQuestionBankVO> page(ActivityQuestionBankQuery query) {
        IPage<ActivityQuestionBankEntity> page = baseMapper.selectPage(getPage(query), getWrapper(query));

        return new PageResult<>(BeanUtil.copyToList(page.getRecords(), ActivityQuestionBankVO.class), page.getTotal());
    }

    @Override
    public List<ActivityQuestionBankVO> getAllQuestion() {
        List<ActivityQuestionBankVO> result = BeanUtil.copyToList(this.list(getWrapper(new ActivityQuestionBankQuery())), ActivityQuestionBankVO.class);
        if (CollectionUtils.isNotEmpty(result)) {
            List<Long> questionBankIdList = result.stream().map(ActivityQuestionBankVO::getId).toList();
            List<ActivityQuestionBankOptionVO> bankOptionVOList = activityQuestionBankOptionService.getOptionByQuestionId(questionBankIdList);
            if (CollectionUtils.isNotEmpty(bankOptionVOList)) {
                Map<Long, List<ActivityQuestionBankOptionVO>> questionOptionMap = bankOptionVOList.stream().collect(Collectors.groupingBy(ActivityQuestionBankOptionVO::getQuestionId));
                result.forEach(item -> {
                    item.setOptions(questionOptionMap.getOrDefault(item.getId(), new ArrayList<>()));
                });
            }
        }
        return result;
    }

    private LambdaQueryWrapper<ActivityQuestionBankEntity> getWrapper(ActivityQuestionBankQuery query) {
        LambdaQueryWrapper<ActivityQuestionBankEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.like(StringUtils.isNotEmpty(query.getQuestionTitle()), ActivityQuestionBankEntity::getQuestionTitle, query.getQuestionTitle())
                .eq(ObjectUtils.isNotEmpty(query.getQuestionType()), ActivityQuestionBankEntity::getQuestionType, query.getQuestionType())
                .eq(ObjectUtils.isNotEmpty(query.getQuestionClassify()), ActivityQuestionBankEntity::getQuestionClassify, query.getQuestionClassify());
        dataScopeWrapper(wrapper);
        return wrapper;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(ActivityQuestionBankOperateVO vo) {
        ActivityQuestionBankEntity entity = BeanUtil.copyProperties(vo, ActivityQuestionBankEntity.class);
        entity.setOrgId(SecurityUser.getUser().getOrgId());
        baseMapper.insert(entity);
        shareInsert(entity.getId(), vo.getOptions());
    }

    @Override
    public ActivityQuestionBankOperateVO getInfoById(Long id) {
        ActivityQuestionBankOperateVO result = BeanUtil.copyProperties(this.getById(id), ActivityQuestionBankOperateVO.class);
        result.setOptions(activityQuestionBankOptionService.getOptionByQuestionId(Collections.singletonList(id)));
        return result;
    }

    /**
     * 共用
     *
     * @param id      主键
     * @param options 选项
     */
    private void shareInsert(Long id, List<ActivityQuestionBankOptionVO> options) {
        if (CollectionUtils.isNotEmpty(options)) {
            List<ActivityQuestionBankOptionEntity> entityList = BeanUtil.copyToList(options, ActivityQuestionBankOptionEntity.class);
            entityList.forEach(item -> {
                item.setQuestionId(id);
                item.setId(null);
            });
            activityQuestionBankOptionService.saveBatch(entityList);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(ActivityQuestionBankOperateVO vo) {
        ActivityQuestionBankEntity entity = BeanUtil.copyProperties(vo, ActivityQuestionBankEntity.class);
        updateById(entity);
        activityQuestionBankOptionService.remove(new LambdaQueryWrapper<ActivityQuestionBankOptionEntity>().eq(ActivityQuestionBankOptionEntity::getQuestionId, entity.getId()));
        shareInsert(entity.getId(), vo.getOptions());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteDataById(List<Long> idList) {
        removeByIds(idList);
        activityQuestionBankOptionService.remove(new LambdaQueryWrapper<ActivityQuestionBankOptionEntity>().in(ActivityQuestionBankOptionEntity::getId, idList));
    }

    private final static List<Function<ActivityQuestionBankExcelVO, String>> BANK_QUESTION_MAP_GETTER = List.of(ActivityQuestionBankExcelVO::getOptionTitleA, ActivityQuestionBankExcelVO::getOptionTitleB, ActivityQuestionBankExcelVO::getOptionTitleC, ActivityQuestionBankExcelVO::getOptionTitleD
            , ActivityQuestionBankExcelVO::getOptionTitleE, ActivityQuestionBankExcelVO::getOptionTitleF, ActivityQuestionBankExcelVO::getOptionTitleG, ActivityQuestionBankExcelVO::getOptionTitleH);

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importByExcel(MultipartFile file) throws IOException {
        try (ExcelReader reader = ExcelUtil.getReader(file.getInputStream())) {
            // 获取所有Sheet名称
            List<Sheet> sheets = reader.getSheets();

            sheets.forEach(sheet -> {
                // 动态切换当前读取的Sheet
                reader.setSheet(sheet.getSheetName());
                switch (sheet.getSheetName()) {
                    case "单选题":
                        singleOrMultipleChoice(reader, 0);
                        break;
                    case "多选题":
                        singleOrMultipleChoice(reader, 1);
                        break;
                    case "判断题":
                        judgmentQuestion(reader, 2);
                        break;
                    default:
                        break;
                }
            });
        }
    }

    /**
     * 单选题读取数据
     *
     * @param reader       读取
     * @param questionType 题目类型
     */
    private void singleOrMultipleChoice(ExcelReader reader, Integer questionType) {
        List<ActivityQuestionBankExcelVO> result = reader.readAll(ActivityQuestionBankExcelVO.class);
        ExcelUtils.parseDict(result);
        result.forEach(item -> {
            ActivityQuestionBankOperateVO bankOperateVO = new ActivityQuestionBankOperateVO();
            bankOperateVO.setQuestionTitle(item.getQuestionTitle());
            bankOperateVO.setQuestionType(questionType);
            bankOperateVO.setQuestionClassify(item.getQuestionClassify());
            String whetherCorrectAnswer = item.getWhetherCorrectAnswer();
            if (StringUtils.isNotEmpty(whetherCorrectAnswer)) {
                List<Integer> indexList = getAnswerIndex(whetherCorrectAnswer);
                List<String> optionTitleList = new ArrayList<>();
                BANK_QUESTION_MAP_GETTER.forEach(getterItem -> {
                    String optionTitle = getterItem.apply(item);
                    if (StringUtils.isNotEmpty(optionTitle)) {
                        optionTitleList.add(optionTitle);
                    }
                });
                importSave(bankOperateVO, optionTitleList, indexList);
            }
        });
    }

    /**
     * 获取下标
     *
     * @param answer
     * @return
     */
    private List<Integer> getAnswerIndex(String answer) {
        List<String> letters = answer.chars()
                .mapToObj(c -> String.valueOf((char) c))
                .toList();
        List<Integer> indices = new ArrayList<>();
        for (String letter : letters) {
            int index = ExcelImportUtil.OPTION_INDEX.indexOf(letter);
            if (index != -1) {
                indices.add(index);
            }
        }
        return indices;
    }

    /**
     * 导入插入数据
     *
     * @param vo        题目
     * @param options   选项
     * @param indexList 正确答案下标
     */
    private void importSave(ActivityQuestionBankOperateVO vo, List<String> options, List<Integer> indexList) {
        ActivityQuestionBankEntity entity = BeanUtil.copyProperties(vo, ActivityQuestionBankEntity.class);
        entity.setOrgId(SecurityUser.getUser().getOrgId());
        baseMapper.insert(entity);
        List<ActivityQuestionBankOptionVO> optionVOList = options.stream()
                .map(option -> new ActivityQuestionBankOptionVO()
                        .setOptionTitle(option)
                        .setWhetherCorrectAnswer(indexList.contains(options.indexOf(option)) ? Constant.ENABLE : Constant.DISABLE))
                .collect(Collectors.toList());
        shareInsert(entity.getId(), optionVOList);
    }

    /**
     * 判断题插入库
     *
     * @param reader       读取
     * @param questionType 题目类型
     */
    private void judgmentQuestion(ExcelReader reader, Integer questionType) {
        List<ActivityQuestionBankExcelVO> result = reader.readAll(ActivityQuestionBankExcelVO.class);
        ExcelUtils.parseDict(result);
        result.forEach(item -> {
            ActivityQuestionBankEntity entity = new ActivityQuestionBankEntity();
            entity.setQuestionTitle(item.getQuestionTitle());
            entity.setQuestionType(questionType);
            entity.setQuestionClassify(item.getQuestionClassify());
            entity.setWhetherCorrect(JudgmentAnserEnum.getStatus(item.getWhetherCorrectAnswer()));
            baseMapper.insert(entity);
        });
    }

    @Override
    public void export(Integer type) {
        try (ExcelWriter writer = ExcelUtil.getWriter(true)) {
            writer.getWorkbook().removeSheetAt(0);
            // 获取分类数据
            if (type.equals(Constant.ENABLE)) {
                Map<QuestionType, List<ActivityQuestionBankExcelCopyVO>> dataMap = prepareExportData();
                // 动态创建Sheet
                dataMap.forEach((questionType, voList) -> {
                    writer.setSheet(questionType.getSheetName());
                    if (!questionType.getCode().equals(QuestionType.JUDGMENT.getCode())) {
                        List<ActivityQuestionBankExportVO> exportVOList = new ArrayList<>();
                        voList.forEach(item -> {
                            ActivityQuestionBankExportVO activityQuestionBankExportVO = new ActivityQuestionBankExportVO();
                            activityQuestionBankExportVO.setQuestionTitle(item.getQuestionTitle());
                            activityQuestionBankExportVO.setOptionTitleA(item.getOptionTitleA());
                            activityQuestionBankExportVO.setOptionTitleB(item.getOptionTitleB());
                            activityQuestionBankExportVO.setOptionTitleC(item.getOptionTitleC());
                            activityQuestionBankExportVO.setOptionTitleD(item.getOptionTitleD());
                            activityQuestionBankExportVO.setOptionTitleE(item.getOptionTitleE());
                            activityQuestionBankExportVO.setOptionTitleF(item.getOptionTitleF());
                            activityQuestionBankExportVO.setOptionTitleG(item.getOptionTitleG());
                            activityQuestionBankExportVO.setOptionTitleH(item.getOptionTitleH());
                            activityQuestionBankExportVO.setQuestionClassifyName(item.getQuestionClassifyName());
                            activityQuestionBankExportVO.setWhetherCorrectAnswer(item.getWhetherCorrectAnswer());
                            exportVOList.add(activityQuestionBankExportVO);
                        });
                        writer.write(exportVOList, true);
                    } else {
                        List<ActivityQuestionBankJudgmentExportVO> exportVOList = new ArrayList<>();
                        voList.forEach(item -> {
                            ActivityQuestionBankJudgmentExportVO bankJudgmentExportVO = new ActivityQuestionBankJudgmentExportVO();
                            bankJudgmentExportVO.setQuestionTitle(item.getQuestionTitle());
                            bankJudgmentExportVO.setWhetherCorrectAnswer(item.getWhetherCorrectAnswer());
                            bankJudgmentExportVO.setQuestionClassifyName(item.getQuestionClassifyName());
                            exportVOList.add(bankJudgmentExportVO);
                        });
                        writer.write(exportVOList, true);
                    }
                });
            } else {
                Arrays.stream(QuestionType.values()).forEach(item -> {
                    writer.setSheet(item.getSheetName());
                    if (!item.getCode().equals(QuestionType.JUDGMENT.getCode())) {
                        List<ActivityQuestionBankExportVO> exportVOList = new ArrayList<>();
                        exportVOList.add(new ActivityQuestionBankExportVO());
                        writer.write(exportVOList, true);
                    } else {
                        List<ActivityQuestionBankJudgmentExportVO> exportVOList = new ArrayList<>();
                        exportVOList.add(new ActivityQuestionBankJudgmentExportVO());
                        writer.write(exportVOList, true);
                    }
                });
            }
            // 设置下载响应（示例使用HttpServletResponse）
            HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            String fileName = "题目清单" + DateUtils.format(new Date(), DateUtils.DATE_TIME_PATTERN) + ".xlsx";
            String encodedFileName = URLEncoder.encode(fileName, "UTF-8")
                    .replaceAll("\\+", "%20");
            response.setHeader("Content-Disposition",
                    "attachment; filename=\"" + encodedFileName + "\"; " +
                            "filename*=UTF-8''" + encodedFileName);
            writer.flush(response.getOutputStream());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 数据准备方法
     *
     * @return 结果
     */
    private Map<QuestionType, List<ActivityQuestionBankExcelCopyVO>> prepareExportData() {
        Map<QuestionType, List<ActivityQuestionBankExcelCopyVO>> dataMap = new LinkedHashMap<>();
        LambdaQueryWrapper<ActivityQuestionBankEntity> wrapper = Wrappers.lambdaQuery();
        if (!SecurityUser.getUser().getSuperAdmin().equals(Constant.SUPER_ADMIN)) {
            wrapper.eq(ActivityQuestionBankEntity::getOrgId, SecurityUser.getUser().getOrgId());
        }
        List<Integer> check = Arrays.asList(QuestionType.SINGLE_CHOICE.getCode(), QuestionType.MULTI_CHOICE.getCode());
        List<ActivityQuestionBankEntity> list = list(wrapper);
        if (CollectionUtils.isNotEmpty(list)) {
            Map<Integer, List<ActivityQuestionBankEntity>> listMap = list.stream().collect(Collectors.groupingBy(ActivityQuestionBankEntity::getQuestionType));
            Arrays.stream(QuestionType.values()).forEach(type -> {
                List<ActivityQuestionBankEntity> entities = listMap.get(type.getCode());
                if (CollectionUtils.isNotEmpty(entities)) {
                    List<ActivityQuestionBankExcelCopyVO> voList = BeanUtil.copyToList(entities, ActivityQuestionBankExcelCopyVO.class);
                    if (check.contains(type.getCode())) {
                        processOptions(voList);
                    } else {
                        voList.forEach(item -> {
                            item.setWhetherCorrectAnswer(item.getWhetherCorrect().equals(JudgmentAnserEnum.CORRECT.getStatus()) ? JudgmentAnserEnum.CORRECT.getMsg() : JudgmentAnserEnum.ERROR.getMsg());
                        });
                    }
                    transService.transBatch(voList);
                    dataMap.put(type, voList);
                }
            });
        }
        return dataMap;
    }

    /**
     * 对应的字段
     */
    private static final List<BiConsumer<ActivityQuestionBankExcelCopyVO, String>> BANK_QUESTION_MAP_SETTER =
            List.of(
                    ActivityQuestionBankExcelCopyVO::setOptionTitleA,
                    ActivityQuestionBankExcelCopyVO::setOptionTitleB,
                    ActivityQuestionBankExcelCopyVO::setOptionTitleC,
                    ActivityQuestionBankExcelCopyVO::setOptionTitleD,
                    ActivityQuestionBankExcelCopyVO::setOptionTitleE,
                    ActivityQuestionBankExcelCopyVO::setOptionTitleF,
                    ActivityQuestionBankExcelCopyVO::setOptionTitleG,
                    ActivityQuestionBankExcelCopyVO::setOptionTitleH
            );

    /**
     * 设置选项
     *
     * @param voList 题目
     */
    private void processOptions(List<ActivityQuestionBankExcelCopyVO> voList) {
        if (CollectionUtils.isNotEmpty(voList)) {
            List<Long> questionIds = voList.stream()
                    .map(ActivityQuestionBankExcelCopyVO::getId)
                    .collect(Collectors.toList());

            Map<Long, List<ActivityQuestionBankOptionVO>> optionMap = activityQuestionBankOptionService
                    .getOptionByQuestionId(questionIds)
                    .stream()
                    .collect(Collectors.groupingBy(ActivityQuestionBankOptionVO::getQuestionId));

            voList.forEach(item -> {
                List<ActivityQuestionBankOptionVO> optionVOList = optionMap.getOrDefault(item.getId(), Collections.emptyList());
                if (CollectionUtils.isNotEmpty(optionVOList)) {
                    StringBuilder answer = new StringBuilder();
                    for (int i = 0; i < optionVOList.size(); i++) {
                        ActivityQuestionBankOptionVO option = optionVOList.get(i);
                        BANK_QUESTION_MAP_SETTER.get(i).accept(item, option.getOptionTitle());
                        if (option.getWhetherCorrectAnswer().equals(Constant.ENABLE)) {
                            answer.append(ExcelImportUtil.OPTION_INDEX.get(i));
                        }
                    }
                    item.setWhetherCorrectAnswer(answer.toString());
                }
            });
        }
    }


//    @Override
//    public void export(Integer type) {
//        List<ActivityQuestionBankExcelVO> activityQuestionBankExcelVOList = new ArrayList<>();
//        if (type.equals(Constant.ENABLE)) {
//            LambdaQueryWrapper<ActivityQuestionBankEntity> wrapper = Wrappers.lambdaQuery(ActivityQuestionBankEntity.class);
//            if (!SecurityUser.getUser().getSuperAdmin().equals(Constant.SUPER_ADMIN)) {
//                wrapper.eq(ActivityQuestionBankEntity::getOrgId, SecurityUser.getUser().getOrgId());
//            }
//            List<ActivityQuestionBankEntity> list = list(wrapper);
//            Map<QuestionType, List<ActivityQuestionBankExcelVO>> dataMap = new LinkedHashMap<>();
//            activityQuestionBankExcelVOList = BeanUtil.copyToList(list, ActivityQuestionBankExcelVO.class);
//            if (CollectionUtils.isNotEmpty(activityQuestionBankExcelVOList)) {
//                List<Long> questionIdList = activityQuestionBankExcelVOList.stream().map(ActivityQuestionBankExcelVO::getId).collect(Collectors.toList());
//                List<ActivityQuestionBankOptionVO> questionBankOptionList = activityQuestionBankOptionService.getOptionByQuestionId(questionIdList);
//                if (CollectionUtils.isNotEmpty(questionBankOptionList)) {
//                    Map<Long, List<ActivityQuestionBankOptionVO>> optionMap = questionBankOptionList.stream().collect(Collectors.groupingBy(ActivityQuestionBankOptionVO::getQuestionId));
//                    activityQuestionBankExcelVOList.forEach(item -> {
//                        List<ActivityQuestionBankOptionVO> optionVOList = optionMap.get(item.getId());
//                        if (CollectionUtils.isNotEmpty(optionVOList)) {
//                            for (int i = 0; i < optionVOList.size(); i++) {
//                                ActivityQuestionBankOptionVO option = optionVOList.get(i);
//                                Iterables.get(BANK_QUESTION_MAP_SETTER, i).accept(item, option.getOptionTitle());
//                                if (option.getWhetherCorrectAnswer().equals(Constant.ENABLE)) {
//                                    item.setWhetherCorrectAnswer(ExcelImportUtil.OPTION_INDEX.get(i));
//                                }
//                            }
//                        }
//                    });
//                }
//            }
//        }
//        ExcelUtils.excelExport(ActivityQuestionBankExcelVO.class, "题目管理", "单选题", activityQuestionBankExcelVOList);
//    }

}